const co = require('co');
const models = require('../models');
const logger = require('../utils/logger');
const config = require('../config/config.json');
var Sequelize = require('sequelize');
const Op = Sequelize.Op

/**
 * 查询交易记录（从本地区块数据库里面查询）
 * url query 参数：
 * type 类型： transfer 转账（包括转出，转入）,transfer_in 只查询转入， transfer_out 只查询转出， others 其它交易
 * accountName： 哪个账号发生的交易
 * pageSize： 分页数据每一页多少条数据
 * rowIndex： 分页数据从第几行开始
 */
let queryActionHisrotyInSyncData = co.wrap(function* (actionType, accountName, currency, pageSize, rowIndex) {

    let datas = [];
    let qryWhere = null;

    const noData = {
        count: 0,
        last_irreversible_block: 0,
        rows: []
    };

    if (actionType == "transfer") {
        qryWhere = {
            "action_name": "transfer",
            [Op.or]: [{ "account_from": accountName }, { "account_to": accountName }] // 转入和转出
        };
    } else if (actionType == "transfer_in") {
        qryWhere = {
            "action_name": "transfer",
            "account_to": accountName
        };
    } else if (actionType == "transfer_out") {
        qryWhere = {
            "action_name": "transfer",
            "account_from": accountName
        };
    } else if (actionType == "others") {
        qryWhere = {
            "action_name": { [Op.ne]: "transfer" },  // 其它非transfer的交易
            [Op.or]: [{ "account_from": accountName }, { "account_to": accountName }]
        };
    }
    if (qryWhere == null) {
        logger.error("error query params");
        return noData;
    }
    if (currency && currency != "") {
        qryWhere.quantity = { [Op.like]: "%" + currency };
    }

    try {
        datas = yield models.eos_action.findAndCountAll({
            where: qryWhere,
            offset: rowIndex,
            limit: pageSize,
            order: [["action_time", "desc"]]
        });
    } catch (e) {
        logger.error(e.message);
        return noData;
    }

    return datas;

});

/**
 * 通过在线查询链上数据的方式返回交易记录
 */
let queryActionHisrotyInEosEndpoint = co.wrap(function* (actionType, accountName, currency) {

    if (actionType == null || actionType == "") {
        actionType = "transfer";
    }

    let reqParam = {
        pos: -1,
        offset: -500,
        account_name: accountName
    };

    const resp = yield fetch('http://api1.eosasia.one/v1/history/get_actions', {
        method: 'POST',
        body: JSON.stringify(reqParam),
        headers: { 'Content-Type': 'application/json' },
    });
    let jsonContent = yield resp.json();

    const last_irreversible_block = jsonContent.last_irreversible_block;
    const actionList = jsonContent.actions;

    let datas = [];
    let maxLength = 50; // 只查询最近50条记录
    // 根据返回的数据， 需要倒序，把最新的放在前面
    for (let i = actionList.length - 1; i >= 0; i--) {
        const item = actionList[i];
        if (item.action_trace && item.action_trace.act && item.action_trace.act.data && item.action_trace.receipt) {
            const receiver = item.action_trace.receipt.receiver;
            const quantity = item.action_trace.act.data.quantity;
            const action_name = item.action_trace.act.name;
            const blockNum = item.block_num;
            const transId = item.action_trace.trx_id;
            if (quantity && quantity.indexOf(" " + currency) == -1 || receiver !== accountName) {
                continue;
            }
            if (action_name !== actionType) {
                continue;
            }
            // 注意：以下关于block_time的有待确认（试过美国节点、亚洲节点、中国节点）
            // http://api1.eosasia.one, http://api1.eosasia.one, https://mainnet.more.top/
            // 从api取回的数据中分析，block_time 是美国太平洋时区（旧金山/加州 UTC/GMT -8小时）的时间。
            // 所以要将这个时间转为 GMT0 的标准时间，也就是将这个时间+8小时(3600000微秒 * 8)，GMT0在手机可以自动转成当地时区的时间
            const timestamp = new Date(item.block_time).getTime();
            //const timestamp_GMT0 = timestamp + (3600000 * 8);  // 加8个小时转为GMT0， 得到的这个标准GMT0时间，APP会自动根据手机所在时区转换成当地时间
            const timestamp_GMT0 = timestamp;  // 发现在eoswalletservice服务器上面，不用转时区, 假如要转时区，用上面一行代码调整
            // ----------- END OF TIME
            const aData = {
                is_confirm: blockNum <= last_irreversible_block,
                block_num: blockNum,
                trans_id: transId,
                action_seq: item.account_action_seq,
                action_time: timestamp_GMT0,
                action_name: action_name,
                account_from: item.action_trace.act.data.from,
                account_to: item.action_trace.act.data.to,
                quantity: item.action_trace.act.data.quantity,
                memo: item.action_trace.act.data.memo,
            };
            datas.push(aData);
            maxLength--;
            if (maxLength == 0) { // 只返回最近50条记录
                break;
            }
        }
    }

    const result = {
        count: datas.length,
        last_irreversible_block: last_irreversible_block,
        rows: datas
    };

    return result;
});

/**
 * 提供给外部调用的接口
 */
let queryActionHisroty = co.wrap(function* (apiType, actionType, accountName, currency, pageSize, rowIndex) {
    let isFromEndpoint = config.queryActionHistoryFromEosEndpoint;
    if (isFromEndpoint == null) {
        isFromEndpoint = true;
    }
    if (apiType === "sync_data") {
        isFromEndpoint = false; // APP端强制使用 sync_data 接口查询历史记录
    }

    let datas = {
        count: 0,
        last_irreversible_block: null,
        rows: []
    };

    if (isFromEndpoint === false) {
        datas = yield queryActionHisrotyInSyncData(actionType, accountName, currency, pageSize, rowIndex);
    } else {
        datas = yield queryActionHisrotyInEosEndpoint(actionType, accountName, currency);
    }
    return datas;
});


module.exports = {
    queryActionHisroty
};

